/*
 * Copyright (C) 2023-2025 Intel Corporation
 *
 * SPDX-License-Identifier: MIT
 *
 */

#ifndef _ZET_INTEL_GPU_METRIC_H
#define _ZET_INTEL_GPU_METRIC_H

#include "level_zero/ze_intel_results.h"
#include "level_zero/ze_stypes.h"
#include <level_zero/zet_api.h>

#if defined(__cplusplus)
#pragma once
extern "C" {
#endif

#include <stdint.h>

#define ZET_INTEL_GPU_METRIC_VERSION_MAJOR 0
#define ZET_INTEL_GPU_METRIC_VERSION_MINOR 2
#define ZET_INTEL_MAX_METRIC_GROUP_NAME_PREFIX_EXP 64u
#define ZET_INTEL_METRIC_PROGRAMMABLE_PARAM_TYPE_GENERIC_EXP (0x7ffffffe)

#ifndef ZET_INTEL_METRIC_SOURCE_ID_EXP_NAME
/// @brief Extension name for query to read the Intel Metric source ID
#define ZET_INTEL_METRIC_SOURCE_ID_EXP_NAME "ZET_intel_metric_source_id"
#endif // ZET_INTEL_METRIC_SOURCE_ID_EXP_NAME

///////////////////////////////////////////////////////////////////////////////
/// @brief Metric Source Id extension Version(s)
typedef enum _zet_intel_metric_source_id_exp_version_t {
    ZET_INTEL_METRIC_SOURCE_ID_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0),     ///< version 1.0
    ZET_INTEL_METRIC_SOURCE_ID_EXP_VERSION_CURRENT = ZE_MAKE_VERSION(1, 0), ///< latest known version
    ZET_INTEL_METRIC_SOURCE_ID_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
} zet_intel_metric_source_id_exp_version_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Query an unique identifier representing the source of a metric group
/// This structure can be passed in the 'pNext' of zet_metric_group_properties_t
typedef struct _zet_intel_metric_source_id_exp_t {
    zet_structure_type_ext_t stype; ///< [in] type of this structure
    const void *pNext;              ///< [in][optional] must be null or a pointer to an extension-specific
                                    ///< structure (i.e. contains stype and pNext).
    uint32_t sourceId;              ///< [out] Returns an unique source Id of the metric group
} zet_intel_metric_source_id_exp_t;

#ifndef ZET_INTEL_METRIC_APPEND_MARKER_EXP_NAME
/// @brief Extension name for query to read the Intel Metric append marker
#define ZET_INTEL_METRIC_APPEND_MARKER_EXP_NAME "ZET_intel_metric_append_marker"
#endif // ZET_INTEL_APPEND_MARKER_EXP_NAME

///////////////////////////////////////////////////////////////////////////////
/// @brief Append Marker extension Version(s)
typedef enum _zet_intel_metric_append_marker_exp_version_t {
    ZET_INTEL_METRIC_APPEND_MARKER_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0),     ///< version 1.0
    ZET_INTEL_METRIC_APPEND_MARKER_EXP_VERSION_CURRENT = ZE_MAKE_VERSION(1, 0), ///< latest known version
    ZET_INTEL_METRIC_APPEND_MARKER_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
} zet_intel_metric_append_marker_exp_version_t;

#define ZET_INTEL_METRIC_GROUP_TYPE_EXP_FLAG_MARKER (static_cast<zet_metric_group_type_exp_flags_t>(ZE_BIT(3)))

///////////////////////////////////////////////////////////////////////////////
/// @brief Appends a metric marker to the command list based on the metricGroup
/// Metrics can be generated by multiple sources in the HW
/// This API generates a marker through the same source as the metric group
ze_result_t ZE_APICALL zetIntelCommandListAppendMarkerExp(zet_command_list_handle_t hCommandList,
                                                          zet_metric_group_handle_t hMetricGroup,
                                                          uint32_t value);

typedef zet_metric_tracer_exp_desc_t zet_intel_metric_tracer_exp_desc_t;
typedef zet_metric_tracer_exp_handle_t zet_intel_metric_tracer_exp_handle_t;
typedef zet_metric_decoder_exp_handle_t zet_intel_metric_decoder_exp_handle_t;
typedef zet_metric_entry_exp_t zet_intel_metric_entry_exp_t;

ze_result_t ZE_APICALL zetIntelMetricTracerCreateExp(
    zet_context_handle_t hContext,                       ///< [in] handle of the context object
    zet_device_handle_t hDevice,                         ///< [in] handle of the device
    uint32_t metricGroupCount,                           ///< [in] metric group count
    zet_metric_group_handle_t *phMetricGroups,           ///< [in][range(0, metricGroupCount )] handles of the metric groups to
                                                         ///< trace
    zet_intel_metric_tracer_exp_desc_t *desc,            ///< [in,out] metric tracer descriptor
    ze_event_handle_t hNotificationEvent,                ///< [in][optional] event used for report availability notification. Note:
                                                         ///< If buffer is not drained when the event it flagged, there is a risk of
                                                         ///< HW event buffer being overrun
    zet_intel_metric_tracer_exp_handle_t *phMetricTracer ///< [out] handle of the metric tracer
);

ze_result_t ZE_APICALL zetIntelMetricTracerDestroyExp(
    zet_intel_metric_tracer_exp_handle_t hMetricTracer ///< [in] handle of the metric tracer
);

ze_result_t ZE_APICALL zetIntelMetricTracerEnableExp(
    zet_intel_metric_tracer_exp_handle_t hMetricTracer, ///< [in] handle of the metric tracer
    ze_bool_t synchronous                               ///< [in] request synchronous behavior. Confirmation of successful
                                                        ///< asynchronous operation is done by calling ::zetMetricTracerReadDataExp()
                                                        ///< and checking the return status: ::ZE_RESULT_NOT_READY will be returned
                                                        ///< when the tracer is inactive. ::ZE_RESULT_SUCCESS will be returned
                                                        ///< when the tracer is active.
);

ze_result_t ZE_APICALL zetIntelMetricTracerDisableExp(
    zet_intel_metric_tracer_exp_handle_t hMetricTracer, ///< [in] handle of the metric tracer
    ze_bool_t synchronous                               ///< [in] request synchronous behavior. Confirmation of successful
                                                        ///< asynchronous operation is done by calling ::zetMetricTracerReadDataExp()
                                                        ///< and checking the return status: ::ZE_RESULT_SUCCESS will be returned
                                                        ///< when the tracer is active or when it is inactive but still has data.
                                                        ///< ::ZE_RESULT_NOT_READY will be returned when the tracer is inactive and
                                                        ///< has no more data to be retrieved.
);

ze_result_t ZE_APICALL zetIntelMetricTracerReadDataExp(
    zet_intel_metric_tracer_exp_handle_t hMetricTracer, ///< [in] handle of the metric tracer
    size_t *pRawDataSize,                               ///< [in,out] pointer to size in bytes of raw data requested to read.
                                                        ///< if size is zero, then the driver will update the value with the total
                                                        ///< size in bytes needed for all data available.
                                                        ///< if size is non-zero, then driver will only retrieve that amount of
                                                        ///< data.
                                                        ///< if size is larger than size needed for all data, then driver will
                                                        ///< update the value with the actual size needed.
    uint8_t *pRawData                                   ///< [in,out][optional][range(0, *pRawDataSize)] buffer containing tracer
                                                        ///< data in raw format
);

ze_result_t ZE_APICALL zetIntelMetricDecoderCreateExp(
    zet_intel_metric_tracer_exp_handle_t hMetricTracer,    ///< [in] handle of the metric tracer
    zet_intel_metric_decoder_exp_handle_t *phMetricDecoder ///< [out] handle of the metric decoder object
);

ze_result_t ZE_APICALL zetIntelMetricDecoderDestroyExp(
    zet_intel_metric_decoder_exp_handle_t phMetricDecoder ///< [in] handle of the metric decoder object
);

ze_result_t ZE_APICALL zetIntelMetricDecoderGetDecodableMetricsExp(
    zet_intel_metric_decoder_exp_handle_t hMetricDecoder, ///< [in] handle of the metric decoder object
    uint32_t *pCount,                                     ///< [in,out] pointer to number of decodable metric in the hMetricDecoder
                                                          ///< handle. If count is zero, then the driver shall
                                                          ///< update the value with the total number of decodable metrics available
                                                          ///< in the decoder. if count is greater than zero
                                                          ///< but less than the total number of decodable metrics available in the
                                                          ///< decoder, then only that number will be returned.
                                                          ///< if count is greater than the number of decodable metrics available in
                                                          ///< the decoder, then the driver shall update the
                                                          ///< value with the actual number of decodable metrics available.
    zet_metric_handle_t *phMetrics                        ///< [in,out] [range(0, *pCount)] array of handles of decodable metrics in
                                                          ///< the hMetricDecoder handle provided.
);

ze_result_t ZE_APICALL zetIntelMetricTracerDecodeExp(
    zet_intel_metric_decoder_exp_handle_t phMetricDecoder, ///< [in] handle of the metric decoder object
    size_t *pRawDataSize,                                  ///< [in,out] size in bytes of raw data buffer. If pMetricEntriesCount is
                                                           ///< greater than zero but less than total number of
                                                           ///< decodable metrics available in the raw data buffer, then driver shall
                                                           ///< update this value with actual number of raw
                                                           ///< data bytes processed.
    uint8_t *pRawData,                                     ///< [in,out][optional][range(0, *pRawDataSize)] buffer containing tracer
                                                           ///< data in raw format
    uint32_t metricsCount,                                 ///< [in] number of decodable metrics in the tracer for which the
                                                           ///< hMetricDecoder handle was provided. See
                                                           ///< ::zetMetricDecoderGetDecodableMetricsExp(). If metricCount is greater
                                                           ///< than zero but less than the number decodable
                                                           ///< metrics available in the raw data buffer, then driver shall only
                                                           ///< decode those.
    zet_metric_handle_t *phMetrics,                        ///< [in] [range(0, metricsCount)] array of handles of decodable metrics in
                                                           ///< the decoder for which the hMetricDecoder handle was
                                                           ///< provided. Metrics handles are expected to be for decodable metrics,
                                                           ///< see ::zetMetricDecoderGetDecodableMetricsExp()
    uint32_t *pSetCount,                                   ///< [in,out] pointer to number of metric sets. If count is zero, then the
                                                           ///< driver shall update the value with the total
                                                           ///< number of metric sets to be decoded. If count is greater than the
                                                           ///< number available in the raw data buffer, then the
                                                           ///< driver shall update the value with the actual number of metric sets to
                                                           ///< be decoded. There is a 1:1 relation between
                                                           ///< the number of sets and sub-devices returned in the decoded entries.
    uint32_t *pMetricEntriesCountPerSet,                   ///< [in,out][optional][range(0, *pSetCount)] buffer of metric entries
                                                           ///< counts per metric set, one value per set.
    uint32_t *pMetricEntriesCount,                         ///< [in,out]  pointer to the total number of metric entries decoded, for
                                                           ///< all metric sets. If count is zero, then the
                                                           ///< driver shall update the value with the total number of metric entries
                                                           ///< to be decoded. If count is greater than zero
                                                           ///< but less than the total number of metric entries available in the raw
                                                           ///< data, then user provided number will be decoded.
                                                           ///< If count is greater than the number available in the raw data buffer,
                                                           ///< then the driver shall update the value with
                                                           ///< the actual number of decodable metric entries decoded. If set to null,
                                                           ///< then driver will only update the value of
                                                           ///< pSetCount.
    zet_intel_metric_entry_exp_t *pMetricEntries           ///< [in,out][optional][range(0, *pMetricEntriesCount)] buffer containing
                                                           ///< decoded metric entries
);
#ifndef ZET_INTEL_METRIC_SCOPES_EXP_NAME
/// @brief Extension name to query Intel Metric Scopes operations
#define ZET_INTEL_METRIC_SCOPES_EXP_NAME "ZET_intel_metric_scopes"
#endif // ZET_INTEL_METRIC_SCOPES_EXP_NAME
typedef enum _zet_intel_metric_scopes_exp_version_t {
    ZET_INTEL_METRIC_SCOPES_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0),                       ///< version 1.0
    ZET_INTEL_METRIC_SCOPES_EXP_VERSION_CURRENT = ZET_INTEL_METRIC_SCOPES_EXP_VERSION_1_0, ///< latest known version
    ZET_INTEL_METRIC_SCOPES_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
} zet_intel_metric_scopes_exp_version_t;

/// @brief Handle of metric scope
struct _zet_intel_metric_scope_exp_handle_t {};
typedef struct _zet_intel_metric_scope_exp_handle_t *zet_intel_metric_scope_exp_handle_t;

#define ZET_INTEL_MAX_METRIC_SCOPE_NAME_EXP 64u
#define ZET_INTEL_MAX_METRIC_SCOPE_DESCRIPTION_EXP 128u

/// @brief Query an metric scope properties
typedef struct _zet_intel_metric_scope_properties_exp_t {
    zet_structure_type_ext_t stype;                               ///< [in] type of this structure
    void *pNext;                                                  ///< [in][optional] must be null or a pointer to an extension-specific
                                                                  ///< structure (i.e. contains stype and pNext).
    uint16_t iD;                                                  ///< [out ]ID will be equal to the index of the metric scope in the
                                                                  ///> array returned by zetIntelMetricScopesGetExp()
    char name[ZET_INTEL_MAX_METRIC_SCOPE_NAME_EXP];               ///< [out] name of the metric scope.
                                                                  ///< The name is expected to be a human readable string.
                                                                  ///< The name can be used to identify the metric scope in the UI.
    char description[ZET_INTEL_MAX_METRIC_SCOPE_DESCRIPTION_EXP]; ///< [out] description of the metric scope.
                                                                  ///< The description is expected to be a human readable string.
} zet_intel_metric_scope_properties_exp_t;

ze_result_t ZE_APICALL zetIntelMetricScopesGetExp(
    zet_context_handle_t hContext,                        ///< [in] handle of the context object
    zet_device_handle_t hDevice,                          ///< [in] handle of the device
    uint32_t *pMetricScopesCount,                         ///< [in,out] pointer to the number of metric scopes available for the device.
                                                          ///< If set to zero, then the driver shall update the value with the total
                                                          ///< number of metric scopes available for the device.
    zet_intel_metric_scope_exp_handle_t *phMetricScopes); ///< [out][optional] [range(0, *pMetricScopesCount)] array of metric scopes handles
                                                          ///< available for the device. If pMetricScopesCount is greater than zero but
                                                          ///< less than the total number of metric scopes available for the device,
                                                          ///< then driver shall only return that number of metric scopes.

ze_result_t ZE_APICALL zetIntelMetricScopeGetPropertiesExp(
    zet_intel_metric_scope_exp_handle_t hMetricScope,                 ///< [in] handle of the metric scope
    zet_intel_metric_scope_properties_exp_t *pMetricScopeProperties); ///< [out] pointer to the metric scope properties structure

#ifndef ZET_INTEL_METRIC_CALCULATION_EXP_NAME
/// @brief Extension name to query Intel Metric Calculation operations
#define ZET_INTEL_METRIC_CALCULATION_EXP_NAME "ZET_intel_metric_calculation"
#endif // ZET_INTEL_METRIC_CALCULATION_EXP_NAME
///////////////////////////////////////////////////////////////////////////////
/// @brief Metric Calculation extension Version(s)
typedef enum _zet_intel_metric_calculation_exp_version_t {
    ZET_INTEL_METRIC_CALCULATION_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0),                            ///< version 1.0
    ZET_INTEL_METRIC_CALCULATION_EXP_VERSION_1_1 = ZE_MAKE_VERSION(1, 1),                            ///< version 1.1
    ZET_INTEL_METRIC_CALCULATION_EXP_VERSION_CURRENT = ZET_INTEL_METRIC_CALCULATION_EXP_VERSION_1_1, ///< latest known version
    ZET_INTEL_METRIC_CALCULATION_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
} zet_intel_metric_calculation_exp_version_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Query metric group calculation properties
/// This structure can be passed in the 'pNext' of zet_metric_group_properties_t
typedef struct _zet_intel_metric_group_calculation_properties_exp_t {
    zet_structure_type_ext_t stype; ///< [in] type of this structure
    void *pNext;                    ///< [in][optional] must be null or a pointer to an extension-specific
                                    ///< structure (i.e. contains stype and pNext).
    bool isTimeFilterSupported;     ///< [out] Flag to indicate if the metric group supports time filtering for
                                    ///< metrics calculation.
} zet_intel_metric_group_calculation_properties_exp_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Query a metric calculable property
/// This structure can be passed in the 'pNext' of zet_metric_properties_t
typedef struct _zet_intel_metric_calculable_properties_exp_t {
    zet_structure_type_ext_t stype; ///< [in] type of this structure
    void *pNext;                    ///< [in][optional] must be null or a pointer to an extension-specific
                                    ///< structure (i.e. contains stype and pNext).
    bool isCalculable;              ///< [out] Flag to indicate if the metric supports calculation.
} zet_intel_metric_calculable_properties_exp_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Handle of metric calculation operation
struct _zet_intel_metric_calculation_operation_exp_handle_t {};
typedef struct _zet_intel_metric_calculation_operation_exp_handle_t *zet_intel_metric_calculation_operation_exp_handle_t;

typedef struct _zet_intel_metric_calculation_time_window_exp_t {
    uint64_t windowStart; ///< [in] starting time in nanoseconds of the raw data to where WindowSize
                          ///< is selected. If WindowStart + WindowSize is bigger than the total
                          ///< time of the raw data collected, only a fraction of the window will be used.
    uint64_t windowSize;  ///< [in] size in nanoseconds of the faction of the raw data used for calculation.
} zet_intel_metric_calculation_time_window_exp_t;

typedef struct _zet_intel_metric_calculation_exp_desc_t {
    zet_structure_type_ext_t stype;                                          ///< [in] type of this structure
    const void *pNext;                                                       ///< [in][optional] must be null or a pointer to an extension-specific
                                                                             ///< structure (i.e. contains stype and pNext).
    uint32_t metricGroupCount;                                               ///< [in] [in] count for metric group handles in metric hMetricGroups array.
                                                                             ///< If set to 0, then phMetricGroups must be null
    zet_metric_group_handle_t *phMetricGroups;                               ///< [in] [optional][range(0, metricGroupCount)] array of metric group
                                                                             ///< handles to filter metric groups to be calculated.
    uint32_t metricCount;                                                    ///< [in] number of metrics handles in the phMetrics array. If set to 0, then
                                                                             ///< phMetrics must be null.
    zet_metric_handle_t *phMetrics;                                          ///< [in][optional] [range(0, metricsCount)] array of metrics handles to filter
                                                                             ///< metrics to be calculated. phMetrics are additionally calculated even if repeated
                                                                             ///< in phMetricGroups.
    uint32_t timeWindowsCount;                                               ///< [in] number of time windows in pCalculationTimeWindows. Must be 0 if disabled.
                                                                             ///< If set to 0, then pCalculationTimeWindows must be null
    zet_intel_metric_calculation_time_window_exp_t *pCalculationTimeWindows; ///< [in][optional][range(0,timeWindowsCount)] array containing the list of time windows
                                                                             ///< to filter metrics data
                                                                             ///< to be used for metrics calculation. Must be null if disabled.
    uint64_t timeAggregationWindow;                                          ///< [in] size in nanoseconds used to divide the raw data and calculate a result for
                                                                             ///< each metric. When enabled, the API will return one report per aggregation
                                                                             ///< window. Must not be 0. When set to uint64_t_MAX will include all rawdata
                                                                             ///< in a single window. If the timeAggregationWindow is bigger than the total
                                                                             ///< time of the raw data collected, will be same as uint64_t_MAX. When
                                                                             ///< timeAggregationWindow is not a perfect divisor of the total time,
                                                                             ///< the last window is expected to be smaller. When CalculationTimeWindows
                                                                             ///< are used, the API will limit the maximum timeAggregationWindow to
                                                                             ///< the size of each CalculationTimeWindow individually. When timeAggregationWindow
                                                                             ///< is smaller than a given CalculationTimeWindow, the CalculationTimeWindow will
                                                                             ///< be divided into timeAggregationWindow sections for aggregation, with the
                                                                             ///< last fraction being smaller when there is no perfect division.
    uint32_t metricScopesCount;                                              ///< [in] number of metric scopes in metric scopes handles. Must not be 0, otherwise error is returned.
    zet_intel_metric_scope_exp_handle_t *phMetricScopes;                     ///< [in][optional] [range (0, metricScopesCount)] array of metric scopes handles to use for calculation.
                                                                             ///< Duplicated entries will be removed. Metrics not supporting all metric scopes listed will be excluded
                                                                             ///< from the calculation operation. If no metric supports all metric scopes included, the calculation
                                                                             ///< operation creation will fail.
} zet_intel_metric_calculation_exp_desc_t;
typedef enum _zet_intel_metric_calculation_result_status_exp_t {
    ZET_INTEL_METRIC_CALCULATION_EXP_RESULT_VALID = 0,
    ZET_INTEL_METRIC_CALCULATION_EXP_RESULT_INVALID,
    ZET_INTEL_METRIC_CALCULATION_EXP_RESULT_FORCE_UINT32 = 0x7fffffff
} zet_intel_metric_calculation_result_status_exp_t;

typedef struct _zet_intel_metric_result_exp_t {
    zet_value_t value;                                             ///< [out] metric result calculated metric value
    zet_intel_metric_calculation_result_status_exp_t resultStatus; ///< [out] type of the result for the filters applied to the calculation.
} zet_intel_metric_result_exp_t;
typedef struct _zet_intel_metric_decoded_buffer_exp_properties_t {
    zet_structure_type_ext_t stype; ///< [in] type of this structure
    void *pNext;                    ///< [in][optional] must be null or a pointer to an extension-specific
                                    ///< structure (i.e. contains stype and pNext).
    uint64_t minTimeStamp;          ///< [out] minimum timestamp contained in the raw data buffer
    uint64_t maxTimeStamp;          ///< [out] maximum timestamp contained in the raw data buffer
} zet_intel_metric_decoded_buffer_exp_properties_t;

ze_result_t ZE_APICALL
zetIntelMetricCalculationOperationCreateExp(
    zet_context_handle_t hContext,                                                ///< [in] handle of the context object
    zet_device_handle_t hDevice,                                                  ///< [in] handle of the device
    zet_intel_metric_calculation_exp_desc_t *pCalculationDesc,                    ///< [in] pointer to structure with filters and operations to perform
                                                                                  ///< at calculation time.
    zet_intel_metric_calculation_operation_exp_handle_t *phCalculationOperation); ///< [out] Calculation operation handle

ze_result_t ZE_APICALL
zetIntelMetricCalculationOperationDestroyExp(
    zet_intel_metric_calculation_operation_exp_handle_t hCalculationOperation); ///< [in] Calculation operation handle

ze_result_t ZE_APICALL zetIntelMetricCalculationOperationGetReportFormatExp(
    zet_intel_metric_calculation_operation_exp_handle_t phCalculationOperation, ///< [in] Calculation operation handle
    uint32_t *pCount,                                                           ///< [in,out] pointer to the number of metrics in the output report from
                                                                                ///< calculation operations. If set to zero, then the driver shall update
                                                                                ///< the value with the total number of metrics to be included in the
                                                                                ///< calculation results report. If count is greater than the total number
                                                                                ///< of metrics to be included in the calculation results report, then the
                                                                                ///< driver shall update the value with the actual number.  If count is
                                                                                ///< smaller than the total number of metrics to be included in the
                                                                                ///< calculation results report, then ZE_RESULT_ERROR_INVALID_ARGUMENT
                                                                                ///< will be returned since this parameter is not intended for
                                                                                ///< filtering metrics.
    zet_metric_handle_t *phMetrics,                                             ///< [out][optional] [range(0, pCount)] array of metrics handles
                                                                                ///< with the order in which results will be found in output report of
                                                                                ///< calculation operations
    zet_intel_metric_scope_exp_handle_t *phMetricScopes);                       ///< [out] [range(0, *pCount)] array of metric scopes handles
                                                                                ///< corresponding to each metric in phMetrics

ze_result_t ZE_APICALL zetIntelMetricCalculationOperationGetExcludedMetricsExp(
    zet_intel_metric_calculation_operation_exp_handle_t phCalculationOperation, ///< [in] Calculation operation handle
    uint32_t *pCount,                                                           ///< [in,out] pointer to the number of metrics excluded from the output report.
                                                                                ///< If set to zero, then the driver shall update the value with the total number
                                                                                ///< of metrics excluded. If count is greater than the total number
                                                                                ///< of metrics excluded, then the driver shall update the value with the
                                                                                ///< actual number. If count is smaller than the total number of metrics
                                                                                ///< excluded then ZE_RESULT_ERROR_INVALID_ARGUMENT will be returned
                                                                                ///< since this parameter is not intended for filtering metrics.
    zet_metric_handle_t *phMetrics);                                            ///< [out][optional] [range(0, pMetricsCount)] array of metrics handles
                                                                                ///< excluded from the output report of calculation operations
ze_result_t ZE_APICALL
zetIntelMetricDecodeCalculateMultipleValuesExp(
    zet_metric_decoder_exp_handle_t hMetricDecoder,                            ///< [in] handle of the metric decoder object
    const size_t rawDataSize,                                                  ///< [in] size in bytes of raw data buffer.
    size_t *offset,                                                            ///< [in,out] On input, the offset from the beginning of pRawData to decode
                                                                               ///< and calculate. On output, the number raw bytes processed
    const uint8_t *pRawData,                                                   ///< [in,out][range(0, *rawDataSize)] buffer containing tracer
                                                                               ///< data in raw format
    zet_intel_metric_calculation_operation_exp_handle_t hCalculationOperation, ///< [in] Calculation operation handle
    uint32_t *pSetCount,                                                       ///< [in,out] pointer to number of metric sets. if count is zero, then the
                                                                               ///< driver shall update the value with the total number of metric sets to
                                                                               ///< be decoded and calculated. If count is greater than the number available
                                                                               ///< in the raw data buffer, then the driver shall update the value with the
                                                                               ///< actual number of metric sets to be decoded and calculated.  There is a
                                                                               ///< 1:1 relationship between the number of sets and the number sub-devices
                                                                               ///< metrics results that can be calculated from the provided data
    uint32_t *pMetricReportCountPerSet,                                        ///< [in,out][optional][range(0, *pSetCount)] buffer of metric reports counts
                                                                               ///< per metric set, one value per set
    uint32_t *pTotalMetricReportCount,                                         ///< [in,out] [optional] pointer to the total number of metric reports decoded and
                                                                               ///< calculated, for all metric sets. If count is zero, then the driver shall update
                                                                               ///< the value with the total number of metric reports to be decoded and calculated.
                                                                               ///< If count is greater than zero but less than the total number of reports available
                                                                               ///< in the raw data, then only that number of reports will be decoded and calculated.
                                                                               ///< If count is greater than the number of reports available in the raw data buffer,
                                                                               ///< then the driver shall update the value with the actual number of metric reports
                                                                               ///< decoded and calculated. If set to null, then driver will only update the value
                                                                               ///< of pSetCount
    zet_intel_metric_result_exp_t *pMetricResults);                            ///< [in,out][optional][range(0, *pTotalMetricResultsCount)] buffer of decoded and
                                                                               ///< calculated metrics results.

ze_result_t ZE_APICALL
zetIntelMetricDecodeToBinaryBufferExp(
    zet_metric_decoder_exp_handle_t hMetricDecoder,                             ///< [in] handle of the metric decoder object
    size_t *pRawDataSize,                                                       ///< [in,out] size in bytes of raw data buffer. If pDecodedBufferSize is greater
                                                                                ///< than 0 but smaller than the total number of bytes required for decoding
                                                                                ///< the entire input raw data, then driver shall update this value with
                                                                                ///< actual number of raw data bytes processed
    const uint8_t *pRawData,                                                    ///< [in,out][range(0, *pRawDataSize)] buffer containing tracer
                                                                                ///< data in raw format
    zet_intel_metric_calculation_operation_exp_handle_t phCalculationOperation, ///< [in] Calculation operation handle, to filter metrics to decode
    zet_intel_metric_decoded_buffer_exp_properties_t *pProperties,              ///< [in] Properties of the decoded buffer.
    size_t *pDecodedBufferSize,                                                 ///< [in] Pointer to the size of the decoded binary buffer. If set to 0,
                                                                                ///< [in,out] Then driver shall update this value with total size in bytes required
                                                                                ///< for the decoded binary buffer. If size is greater than 0 but smaller
                                                                                ///< than the total number of bytes required for decoding entire input
                                                                                ///< raw data, then driver shall only decode an approximate to that number
                                                                                ///< of bytes. If size is greater than the total number of bytes required
                                                                                ///< for decoding entire input raw data, then the driver shall update the
                                                                                ///< value with the actual number of bytes decoded.
    uint8_t *pDecodedBuffer);                                                   ///< [in,out][optional] binary buffer containing decoded raw data.

ze_result_t ZE_APICALL
zetIntelMetricCalculateValuesExp(
    const size_t rawDataSize,                                                  ///< [in] size in bytes of raw data buffer.
    const uint8_t *pRawData,                                                   ///< [in,out][range(0, *rawDataSize)] buffer containing tracer
                                                                               ///< data in raw format
    zet_intel_metric_calculation_operation_exp_handle_t hCalculationOperation, ///< [in] Calculation operation handle
    bool final,                                                                ///< [in] flag to indicate the if the current is the final call for the given data.
                                                                               ///< If false, the driver may cache data as needed for subsequent calls.
                                                                               ///< If true, the driver will finalize the calculations using available data and clear caches.
    size_t *usedDataSize,                                                      ///< [out] The number raw bytes processed. User is expected to advance pRawData
                                                                               ///< pointer by this amount if calling this function subsequently.
    uint32_t *pTotalMetricReportCount,                                         ///< [in,out] [optional] pointer to the total number of metric reports calculated,
                                                                               ///< If count is zero, then the driver shall update the value with the total number of
                                                                               ///< metric reports to be calculated. If count is greater than zero but less than the
                                                                               ///< total number of reports available in the raw data, then only that number of
                                                                               ///< reports will be calculated. If count is greater than the number of reports
                                                                               ///< available in the raw data buffer, then the driver shall update the value with
                                                                               ///< the actual number of metric reports calculated.
    zet_intel_metric_result_exp_t *pMetricResults);                            ///< [in,out][optional][range(0, *pTotalMetricResultsCount)] buffer of calculated
                                                                               ///< metrics results.

#ifndef ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_NAME
/// @brief Extension name for enabling and disabling Intel Metrics collection
#define ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_NAME "ZET_intel_metrics_runtime_enable_disable"
#endif // ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_NAME

///////////////////////////////////////////////////////////////////////////////
/// @brief Metrics Runtime Enable Disable extension Version(s)
typedef enum _zet_intel_metrics_runtime_enable_disable_exp_version_t {
    ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0),                                        ///< version 1.0
    ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_VERSION_CURRENT = ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_VERSION_1_0, ///< latest known version
    ZET_INTEL_METRICS_RUNTIME_ENABLE_DISABLE_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
} zet_intel_metrics_runtime_enable_disable_exp_version_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief This API Enables Metric collection for a device if not already enabled.
/// If device is a root-device, then its sub-devices are also enabled.
/// This API can be used as runtime alternative to setting ZET_ENABLE_METRICS=1.
ze_result_t ZE_APICALL zetIntelDeviceEnableMetricsExp(zet_device_handle_t hDevice);

///////////////////////////////////////////////////////////////////////////////
/// @brief This API Disables Metric for a device, if it was previously enabled.
/// If device is a root-device, then its sub-devices are also disabled.
/// The application has to ensure that all metric operations are complete and
/// all metric resources are released before this API is called.
/// If there are metric operations in progress, then ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE
/// is returned.
ze_result_t ZE_APICALL zetIntelDeviceDisableMetricsExp(zet_device_handle_t hDevice);

#ifndef ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_NAME
/// @brief Extension name for query to read the Intel Level Zero Driver Version String
#define ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_NAME "ZET_intel_get_hw_buffer_size"
#endif // ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_NAME

///////////////////////////////////////////////////////////////////////////////
/// @brief Maximum Hw Buffer Size extension Version(s)
typedef enum _zet_intel_metric_hw_buffer_size_exp_version_t {
    ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_VERSION_1_0 = ZE_MAKE_VERSION(1, 0),                               ///< version 1.0
    ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_VERSION_CURRENT = ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_VERSION_1_0, ///< latest known version
    ZET_INTEL_METRIC_HW_BUFFER_SIZE_EXP_VERSION_FORCE_UINT32 = 0x7fffffff
} zet_intel_metric_hw_buffer_size_exp_version_t;

///////////////////////////////////////////////////////////////////////////////
/// @brief Metric hardware buffer size descriptor
/// This descriptor can be used as a "pNext" value to the zet_metric_streamer_desc_t and zet_metric_tracer_exp_desc_t.
/// This descriptor allow to request and query the allocated HW buffer size in bytes.
/// The sizeInBytes should not be used to estimate buffer overflow scenario (Use notifyNReports to detect it).
typedef struct _zet_intel_metric_hw_buffer_size_exp_desc_t {
    zet_structure_type_ext_t stype; ///< [in] type of this structure
    const void *pNext;              ///< [in][optional] must be null or a pointer to an extension-specific
                                    ///< structure (i.e. contains stype and pNext).
    size_t sizeInBytes;             ///< [in,out] size of the hardware buffer size in bytes.
                                    ///< If the requested value cannot be supported,
                                    ///< then the driver may use a value that can be supported and shall update this member.
                                    ///< When hNotificationEvent is set as input has precedence over hw_buffer_size_exp_desc_t when setting HW buffer size.
                                    ///< The actual size used by the HW will be updated in "sizeInBytes" member by the implementation.
} zet_intel_metric_hw_buffer_size_exp_desc_t;

#if defined(__cplusplus)
} // extern "C"
#endif

#endif //_ZET_INTEL_GPU_METRIC_H
